package com.feishi.core.analytic.packing;

import com.feishi.core.analytic.packing.build.BuildConfig;
import com.feishi.core.analytic.packing.build.BuildSession;
import com.feishi.core.analytic.packing.debuild.DeBuildConfig;
import com.feishi.core.analytic.element.*;
import com.feishi.core.analytic.packing.build.Build;
import com.feishi.core.analytic.packing.build.BuildUtil;
import com.feishi.core.analytic.packing.contentpacking.*;
import com.feishi.core.analytic.packing.debuild.DeBuild;
import com.feishi.core.analytic.packing.debuild.DeBuildSession;
import com.feishi.core.analytic.packing.debuild.DeBuildUtil;
import com.feishi.core.analytic.packing.encode.EncodeParam;
import com.feishi.core.util.common.bean.ByteBufferProxy;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by caixq on 5/9 009.
 */
public class AnalyticDataPacking {
    public final AnalyticBuildPacking analyticBuildPacking;

    public Map<String,AnalyticContentValuePacking> contentValuePackingMap=new HashMap<>();
    public Map<String,AnalyticContentBodyPacking> contentBodyPackingMap=new HashMap<>();
    public Map<String,List<AnalyticContentMapPacking>> contentMapPackingMap =new HashMap<>();
    private Map<String,EncodeParam> encodeParamMap=new HashMap<>();


    public DeBuildSession deBuildSession=new DeBuildSession();
    public BuildSession buildSession=new BuildSession();


    public void putEncodeParam(String name,EncodeParam param){
        encodeParamMap.put(name,param);
    }

    public AnalyticBuildPacking getAnalyticBuildPacking() {
        return analyticBuildPacking;
    }

    public AnalyticDataPacking(AnalyticBuildPacking analyticBuildPacking) {
        this.analyticBuildPacking=analyticBuildPacking;
    }

    public Map<String,Object> dataMap=new HashMap();
    private final Class byteArrayClass=new byte[0].getClass();

    public <T> void setData(String name, T value){
        AnalyticEncodeElement ele = (AnalyticEncodeElement) analyticBuildPacking.getAnalyticElement(name);
        byte[] bytes=ele.getBytes(value);
        dataMap.put(name,bytes);
    }


    public AnalyticContentMapPacking getNewAnalyticContentMapPacking(String name){
        AnalyticContentMapPacking contentPacking = analyticBuildPacking.getAnalyticContentMapPacking(name);
        List<AnalyticContentMapPacking> contentList = contentMapPackingMap.get(name);
        if(contentList==null){
            contentList=new ArrayList<>();
            contentMapPackingMap.put(name,contentList);
        }
        contentPacking.setEncodeParam(this.encodeParamMap.get(name));
        contentList.add(contentPacking);
        return contentPacking;
    }


    public AnalyticContentMapPacking getAnalyticContentMapPacking(String name){
        List<AnalyticContentMapPacking> contentList = contentMapPackingMap.get(name);

        if(contentList==null||contentList.size()==0){
            getNewAnalyticContentMapPacking(name);
            contentList = contentMapPackingMap.get(name);
        }
        return contentList.get(0);
    }
    public List<AnalyticContentMapPacking> getAnalyticContentMapPackings(String name){
        return contentMapPackingMap.get(name);
    }
    public <T> void setData(String name, byte[] bytes){
        dataMap.put(name,bytes);
    }

    public <T> void setData(int name, T value){
        setData(String.valueOf(name),value);
    }


    public  void  setContentDate(String name,byte[] bytes){
        dataMap.put(name,bytes);
    }

    public AnalyticDataPacking deBuild(byte[] bytes){
        List<AnalyticElement> elements = this.analyticBuildPacking.getBody().getElements();
        DeBuild debuild=new DeBuild(bytes,elements);
        debuild.session=deBuildSession;
        DeBuildUtil.deBuild(debuild,this,deBuildConfig().executors);
        return this;
    }



    public boolean isLengthStatic() {
        return analyticBuildPacking.isLengthStatic();
    }

    public int getStaticLength() {
        return analyticBuildPacking.getStaticLength();
    }

    public byte[] build(){
        ByteBufferProxy bfp=new ByteBufferProxy();
        List<AnalyticElement> elements = this.analyticBuildPacking.getBody().getElements();
        Build build=new Build(bfp,elements);
        build.session=buildSession;
        BuildUtil.build(build, this,buildConfig().executors);

        return bfp.get();
    }




    public Object getData(int name) {
        return getData(String.valueOf(name));
    }

    public Object getData(String name) {
        AnalyticElement ele= this.analyticBuildPacking.getElement(name);
        if(ele instanceof AnalyticEncodeElement){
            AnalyticEncodeElement element= (AnalyticEncodeElement) ele;
            byte[] bytesVelue= (byte[]) dataMap.get(name);
            return element.getValue(bytesVelue);
        }else {
            return null;
        }
    }

    public AnalyticContentValuePacking getAnalyticContentValuePacking(String name) {
        AnalyticContentValuePacking contentPacking=contentValuePackingMap.get(name);
        if(contentPacking!=null){
            return contentPacking;
        }
        return getNewAnalyticContentValuePacking(name);
    }
    public AnalyticContentValuePacking getNewAnalyticContentValuePacking(String name) {
        AnalyticContentValuePacking contentPacking = analyticBuildPacking.getAnalyticContentValuePacking(name);
        contentValuePackingMap.put(name,contentPacking);
        return contentPacking;
    }
    public boolean hasContentValuePacking(String name) {
        return analyticBuildPacking.hasContentValuePacking(name);
    }

    public AnalyticContentBodyPacking getNewAnalyticContentBodyPacking(String name) {
        AnalyticContentBodyPacking contentPacking = analyticBuildPacking.getAnalyticContentBodyPacking(name);
        contentBodyPackingMap.put(name,contentPacking);
        return contentPacking;
    }
    public AnalyticContentBodyPacking getAnalyticContentBodyPacking(String name) {
        AnalyticContentBodyPacking contentPacking =contentBodyPackingMap.get(name);
        return contentPacking==null?getNewAnalyticContentBodyPacking(name):contentPacking;
    }

    public void clear() {
        this.contentValuePackingMap.clear();
        this.contentBodyPackingMap.clear();
        this.contentMapPackingMap.clear();
        this.dataMap.clear();
    }

    public BuildConfig buildConfig() {
        return analyticBuildPacking.getBody().buildConfig;
    }
    public DeBuildConfig deBuildConfig() {
        return analyticBuildPacking.getBody().debuildConfig;
    }

    public void addSession(BuildSession buildSession) {
        for (String s : this.buildSession.data.keySet()) {
            buildSession.setAttribute(s,this.buildSession.getAttribute(s));
        }
        this.buildSession=buildSession;
    }
}
